import * as fs from 'fs';
import * as path from 'path';
import { TMakeCompiler } from './compiler';
import { createPluginManager, PluginLifecycleEvent, BuildTargetInfo } from './plugin-system';
import tieBuildPlugin from './plugins/tie-build-plugin';


export interface BuildOptions {
  
  configPath?: string;
  
  silent?: boolean;
  
  watch?: boolean;
  
  outputDir?: string;
  
  clean?: boolean;
  
  compiler?: any;
  
  target?: string;
  
  targetOptions?: Record<string, any>;
  
  sourceFiles?: string[];
  

  output?: string;
  package?: string;
  debug?: boolean;
  release?: boolean;
  hardMode?: boolean;
  optimize?: number;
  disableLint?: string[];
  logLevel?: 'debug' | 'info' | 'warning' | 'error';
  platform?: string;
  lineMap?: string;
  tieccDir?: string;
  customArgs?: string[];
  compilerType?: string;
}


export interface CleanOptions {
  
  silent?: boolean;
  
  compiler?: any;
  
  target?: string;
  
  targetOptions?: Record<string, any>;
}


export class BuildManager {
  private pluginManager: any;
  private compiler: TMakeCompiler;

  constructor(compiler?: TMakeCompiler) {
    this.compiler = compiler || new TMakeCompiler();
    this.pluginManager = createPluginManager(this.compiler);
    
    // 在构造函数中不能直接使用await，所以我们在生成函数描述时手动调用
    // 注意：在正常构建流程中，应该在build方法开始时调用registerDefaultPlugins
  }
  
  // 手动初始化插件
  public async initializePlugins(): Promise<void> {
    await this.registerDefaultPlugins();
  }

  
  private async registerDefaultPlugins(): Promise<void> {
    // 加载内置核心插件
    console.log('加载tieBuildPlugin...');
    this.pluginManager.loadPlugin(tieBuildPlugin);    
    const srcPluginsDir = path.join(__dirname, 'plugins');
    if (fs.existsSync(srcPluginsDir)) {
      console.log(`尝试从 ${srcPluginsDir} 加载插件...`);
      await this.pluginManager.loadPluginsFromDirectory(srcPluginsDir);
    }
    
    // 尝试加载项目目录下的plugins文件夹中的自定义插件
    const projectPluginsDir = path.join(process.cwd(), 'plugins');
    if (fs.existsSync(projectPluginsDir)) {
      console.log(`尝试从 ${projectPluginsDir} 加载插件...`);
      await this.pluginManager.loadPluginsFromDirectory(projectPluginsDir);
    }
    
    // 打印已加载的插件
    console.log('已加载的插件:');
    // @ts-ignore
    for (const [name, { plugin }] of this.pluginManager.plugins) {
      console.log(`- ${name}`);
    }
  }

  
  public getPluginManager(): any {
    return this.pluginManager;
  }

  
  public getCompiler(): TMakeCompiler {
    return this.compiler;
  }

  
  public async build(sourceFiles: string[], options: BuildOptions = {}): Promise<boolean> {
    try {
      console.log('初始化构建环境...');
      
      if (options.output && !options.outputDir) {
        options.outputDir = options.output;
      }

      
      if (options.outputDir) {
        this.compiler.setOutputDir(options.outputDir);
        console.log(`设置输出目录: ${options.outputDir}`);
      }

      
      console.log('准备构建插件...');
      this.pluginManager.emitEvent(PluginLifecycleEvent.BEFORE_BUILD, { ...options, sourceFiles });

      let success = false;
      
      
      const targetName = options.target || this.pluginManager.getDefaultBuildTarget() || 'tie';
      console.log(`使用构建目标: ${targetName}`);
      

      
      
      try {
        success = await this.pluginManager.executeBuildTarget(
          targetName,
          sourceFiles,
          this.prepareTargetOptions(options)
        );
      } catch (err: any) {
        console.error(`执行构建目标失败: ${err.message}`);
        success = false;
      }

      
      this.pluginManager.emitEvent(PluginLifecycleEvent.AFTER_BUILD, success);

      return success;
    } catch (error: any) {
      console.error(`构建过程中发生错误: ${error.message}`);
      return false;
    }
  }

  
  public async clean(options: CleanOptions = {}): Promise<boolean> {
    try {
      
      this.pluginManager.emitEvent(PluginLifecycleEvent.BEFORE_CLEAN, options);

      let success = true;
      
      
      if (options.target) {
        
        const targets = this.pluginManager.getRegisteredBuildTargets();
        const targetInfo = targets.find((t: BuildTargetInfo) => t.name === options.target);
        
        if (targetInfo) {

          
          
        }
      }

      
      this.pluginManager.emitEvent(PluginLifecycleEvent.AFTER_CLEAN, success);

      return success;
    } catch (error: any) {
      console.error(`清理过程中发生错误: ${error.message}`);
      return false;
    }
  }

  
  private prepareTargetOptions(options: BuildOptions): Record<string, any> {
    
    const targetOptions = { ...options };
    
    if (options.targetOptions) {
      Object.assign(targetOptions, options.targetOptions);
    }
    
    return targetOptions;
  }

  
  public listBuildTargets(options: {silent?: boolean} = {}): void {
    // 移除调试日志
    const targets = this.pluginManager.getRegisteredBuildTargets();
    
    targets.forEach((target: BuildTargetInfo) => {
      // 移除调试日志
      if (target.description && !options.silent) {
        // 移除调试日志
      }
      if (target.extensions && target.extensions.length > 0 && !options.silent) {
        // 移除调试日志
      }
    });
  }
}


function showHelp(): void {
  // 移除调试日志
}


export function parseArgs(args: string[]): { command: string; options: Record<string, any>; files: string[] } {
  const result = {
    command: 'build',
    options: {} as Record<string, any>,
    files: [] as string[]
  };

  
  if (args[0] === 'node' || (args[0] && (args[0].endsWith('ts-node') || args[0].endsWith('tmake.js')))) {
    args = args.slice(1);
  }
  if (args[0]?.endsWith('build.ts')) {
    args = args.slice(1);
  }

  
  if (args[0] && ['build', 'clean', 'targets', 'help'].includes(args[0])) {
    result.command = args[0];
    args = args.slice(1);
  }

  
  let i = 0;
  while (i < args.length) {
    const arg = args[i];

    if (arg === '--output-dir' || arg === '-o') {
      i++;
      result.options.outputDir = args[i];
    } else if (arg === '--target' || arg === '-t') {
      i++;
      result.options.target = args[i];
    } else if (arg === '--target-option' || arg === '-to') {
      i++;
      if (!result.options.targetOptions) {
        result.options.targetOptions = {};
      }
      const [key, value] = args[i].split('=');
      result.options.targetOptions[key] = value;
    } else if (arg === '--config' || arg === '-c') {
      i++;
      result.options.configPath = args[i];
    } else if (arg === '--silent' || arg === '-s') {
      result.options.silent = true;
    } else if (arg === '--watch' || arg === '-w') {
      result.options.watch = true;
    } else if (arg === '--tiecc-dir') {
      i++;
      result.options.tieccDir = args[i];
    } else if (arg === '--debug') {
      result.options.debug = true;
    } else if (arg.startsWith('-')) {
      console.warn(`未知选项: ${arg}`);
    } else {
      
      result.files.push(arg);
    }

    i++;
  }

  return result;
}


async function main() {
  const args = parseArgs(process.argv);
  const buildManager = new BuildManager();
  
  switch (args.command) {
    case 'build':
      if (args.files.length === 0) {
        
        const fs = require('fs');
        const path = require('path');
        const files = fs.readdirSync(process.cwd()).filter((file: any) => 
          typeof file === 'string' && file && file.endsWith('.t') && !file.startsWith('__')
        );
        if (files.length > 0) {
          args.files = files.map((file: string) => path.join(process.cwd(), file));
        } else {
          console.error('错误: 未找到任何.t文件');
          process.exit(1);
        }
      }
      
      const success = await buildManager.build(args.files, args.options);
      process.exit(success ? 0 : 1);
      break;

    case 'clean':
      await buildManager.clean(args.options);
      process.exit(0);
      break;

    case 'targets':
      buildManager.listBuildTargets(args.options);
      process.exit(0);
      break;

    case 'help':
    default:
      showHelp();
      process.exit(0);
  }
}


if (require.main === module) {
  main().catch(err => {
    console.error(`错误: ${err.message}`);
    process.exit(1);
  });
}


export async function buildTask(filePaths: string[], options: BuildOptions): Promise<boolean> {
  const buildManager = new BuildManager();
  return buildManager.build(filePaths, options);
}


export async function cleanTask(options: CleanOptions): Promise<boolean> {
  // 移除调试日志
  const buildManager = new BuildManager();
  return buildManager.clean(options);
}